package cn.xiaohuodui.service;

import cn.xiaohuodui.constant.ErrorCodeDefine;
import cn.xiaohuodui.dao.*;
import cn.xiaohuodui.dto.PermissionDto;
import cn.xiaohuodui.exceptions.BussException;
import cn.xiaohuodui.form.back.admin.*;
import cn.xiaohuodui.model.*;
import cn.xiaohuodui.utils.BCrypt;
import cn.xiaohuodui.vo.admin.PermissionVo;
import cn.xiaohuodui.vo.admin.RoleCheckVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Fang
 * @create 2017-05-04 上午10:39
 */
@Service
public class AdminService {

    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    AdminLoginLogMapper adminLoginLogMapper;
    @Autowired
    RoleMapper roleMapper;
    @Autowired
    AdminRoleMapper adminRoleMapper;
    @Autowired
    PermissionMapper permissionMapper;
    @Autowired
    RolePermissionMapper rolePermissionMapper;

    /**
     * 登录  已由 shiro的 `SecurityUtils.getSubject().login(token);` 登录替换
     *
     * @param userLoginForm
     * @return
     * @throws BussException
     */
    @Deprecated
    public Admin login(BAdminLoginForm userLoginForm) throws BussException {
        Admin admin = adminMapper.selectByUsername(userLoginForm.getUsername());
        if (admin == null) {
            throw new BussException(ErrorCodeDefine.DEFAULT_ERROR);
        }
        if (!BCrypt.hashpw(userLoginForm.getPassword(), admin.getSalt()).equals(admin.getPassword())) {
            throw new BussException(ErrorCodeDefine.PASSWORD_NOT_VALID);
        }
        return admin;
    }

    /**
     * 数目统计
     *
     * @param form
     * @return
     */
    public int backCount(AdminBackQueryForm form) {
        Map qm = new HashMap();
        qm.put("username", form.getUsername());

        return adminMapper.backCount(qm);
    }

    /**
     * 查询
     *
     * @param form
     * @return
     */
//    public List<AdminBackDo> backQeury(AdminBackQueryForm form) {
//        Map qm = new HashMap();
//        qm.put("limit", form.getLimit());
//        qm.put("offset", form.getOffset());
//        qm.put("username", form.getUsername());
//
//        return adminMapper.backQuery(qm);
//    }

    /**
     * 保存
     *
     * @param form
     * @throws BussException
     */
    public void save(AdminBackForm form) throws BussException {
        Admin a = adminMapper.selectByUsername(form.getUsername());
        if (a != null) {
            throw new BussException(ErrorCodeDefine.ADMIN_EXISTS);
        }

        Long now = System.currentTimeMillis();
        String salt = BCrypt.gensalt();
        Admin admin = new Admin();
        BeanUtils.copyProperties(form, admin);
        admin.setPassword(BCrypt.hashpw(form.getPassword(), salt));
        admin.setSalt(salt);
        admin.setCreated(now);
        admin.setDeleted(0);

        adminMapper.insertSelective(admin);
    }

    /**
     * 获取 用户的权限组
     * 当AdminId 传 0 的 时候 则 返回所有的可选权限
     *
     * @param adminId
     * @return
     */
    public List<RoleCheckVo> getAdminRoles(int adminId) {
        List<Role> roles = roleMapper.selectByAdminId(adminId);
        List<Integer> exists = roles.stream().map(role -> role.getId()).collect(Collectors.toList());
        List<Role> allRoles = roleMapper.selectAll();

        return allRoles.stream().map(
                role -> {
                    RoleCheckVo roleCheckVo = new RoleCheckVo();
                    BeanUtils.copyProperties(role, roleCheckVo);
                    roleCheckVo.setChecked(exists.contains(role.getId()));
                    return roleCheckVo;
                }
        ).collect(Collectors.toList());
    }

    /**
     * 获取 角色的权限列表
     * 当AdminId 传 0 的 时候 则 返回所有的可选权限
     *
     * @param roleId
     * @return
     */
    public List<PermissionVo> getRolePermissions(int roleId) {
        List<Integer> roleIds = new ArrayList<>();
        roleIds.add(roleId);
        List<PermissionDto> permissions = permissionMapper.selectByRoleIds(roleIds);
        List<Integer> exists = permissions.stream().map(p -> p.getId()).distinct().collect(Collectors.toList());
        List<Permission> allPermissions = permissionMapper.selectAll();

        List<PermissionVo> res = new ArrayList<>();
        PermissionVo all = new PermissionVo();
        all.setId(0);
        all.setPId(0);
        all.setName("全部");
        all.setOpen(true);
        all.setChecked(exists.size() == allPermissions.size());
        res.add(all);
        res.addAll(allPermissions.stream().map(
                p -> {
                    PermissionVo permissionVo = new PermissionVo();
                    permissionVo.setId(p.getId());
                    permissionVo.setName(p.getName());
                    permissionVo.setPId(p.getParentId());
                    if (p.getParentId() == 0) {
                        permissionVo.setOpen(true);
                    }
                    permissionVo.setChecked(exists.contains(p.getId()));
                    return permissionVo;
                }
        ).collect(Collectors.toList()));
        return res;
    }

    /**
     * 获取所有的权限
     *
     * @return
     */
    public List<Permission> getAllPermission() {
        return permissionMapper.selectAll();
    }

    /**
     * 更新管理员的角色
     *
     * @param adminId 管理员id
     * @param roleIds 管理员角色id列表，用逗号分割 例如 1,2,3
     */
    public void updateAdminRoles(int adminId, String roleIds) {
        adminRoleMapper.deleteByAdminId(adminId);

        if (!StringUtils.isEmpty(roleIds)) {
            List<String> roleIdList = Arrays.asList(roleIds.split(","));
            List<AdminRole> adminRoles = roleIdList.stream().map(
                    roleId -> {
                        AdminRole adminRole = new AdminRole();
                        adminRole.setAdminId(adminId);
                        adminRole.setRoleId(Integer.parseInt(roleId));
                        return adminRole;
                    }
            ).collect(Collectors.toList());
            adminRoleMapper.batchInsert(adminRoles);
        }
    }

    /**
     * 删除
     *
     * @param id
     */
    public void remove(Integer id) {
        adminMapper.deleteByPrimaryKey(id);
    }

    /**
     * 更新
     *
     * @param form
     * @throws BussException
     */
    public void update(AdminBackForm form) throws BussException {
        Admin admin = adminMapper.selectByPrimaryKey(form.getId());
        String salt = BCrypt.gensalt();
        if (admin == null) {
            throw new BussException(ErrorCodeDefine.ADMIN_NOT_FOUND);
        }
        BeanUtils.copyProperties(form, admin);
        admin.setSalt(salt);
        admin.setPassword(BCrypt.hashpw(form.getPassword(), salt));

        adminMapper.updateByPrimaryKeySelective(admin);
    }

    /**
     * 更新管理员 最后登录时间
     *
     * @param bAdminLoginForm
     */
    public void updateLastLogin(BAdminLoginForm bAdminLoginForm) {
        adminMapper.updateLastLoginById(bAdminLoginForm.getUid(), bAdminLoginForm.getIp(), System.currentTimeMillis());
        //插入 管理最近登录的日志
        AdminLoginLog adminLoginLog = new AdminLoginLog();
        adminLoginLog.setAdminId(bAdminLoginForm.getUid());
        adminLoginLog.setCreated(System.currentTimeMillis());
        adminLoginLog.setAgent(bAdminLoginForm.getAgent());
        adminLoginLog.setIp(bAdminLoginForm.getIp());
        adminLoginLogMapper.insert(adminLoginLog);
    }


    public Admin selectById(int adminId) {
        Admin admin = adminMapper.selectByPrimaryKey(adminId);
        if (admin == null) {
            admin = new Admin();
        }
        return admin;
    }

    /**
     * 根据用户名获取 admin 对象
     *
     * @param username
     * @return
     */
    public Admin selectByUsername(String username) {
        Admin admin = adminMapper.selectByUsername(username);
        return admin;
    }

    /**
     * 修改密码
     *
     * @param bAdminResetForm
     * @throws BussException
     */
    public void updatePwd(BAdminResetForm bAdminResetForm) throws BussException {
        Admin admin = adminMapper.selectByPrimaryKey(bAdminResetForm.getUid());
        if (admin == null) {
            throw new BussException(ErrorCodeDefine.DEFAULT_ERROR);
        }
        if (!BCrypt.hashpw(bAdminResetForm.getOldPassword(), admin.getSalt()).equals(admin.getPassword())) {
            throw new BussException(ErrorCodeDefine.PASSWORD_NOT_VALID);
        }
        String newPassword = BCrypt.hashpw(bAdminResetForm.getNewPassword(), BCrypt.gensalt());
        admin.setPassword(newPassword);
        adminMapper.updateByPrimaryKey(admin);
    }

    /**
     * 更新角色的权限
     *
     * @param roleId
     * @param roleName
     * @param description
     * @param pids
     */
    public void updateRolePermissions(int roleId, String roleName, String description, String pids) {
        Role role = new Role();
        if (roleId != 0) {
            role = roleMapper.selectByPrimaryKey(roleId);
            role.setDescription(description);
            role.setRole(roleName);
            roleMapper.updateByPrimaryKey(role);
        } else {
            role.setDescription(description);
            role.setRole(roleName);
            role.setCreated(System.currentTimeMillis());
            roleMapper.insert(role);
        }

        rolePermissionMapper.deleteByRoleId(role.getId());

        if (!StringUtils.isEmpty(pids)) {
            List<String> permissionIds = Arrays.asList(pids.split(","));
            Role finalRole = role;
            List<RolePermission> rolePermissions = permissionIds.stream().map(
                    pid -> {
                        RolePermission rolePermission = new RolePermission();
                        rolePermission.setRoleId(finalRole.getId());
                        rolePermission.setPermissionId(Integer.parseInt(pid));
                        return rolePermission;
                    }
            ).collect(Collectors.toList());
            rolePermissionMapper.batchInsert(rolePermissions);
        }
    }

    /**
     * 删除权限组
     *
     * @param roleId
     */
    public void deleteRole(int roleId) {
        roleMapper.deleteByPrimaryKey(roleId);
    }
}
